/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package cuatroenraya;
import cuatroenraya.Jugador;

import java.util.Vector;

/** TRABAJO PRACTICO DE INTELIGENCIA ARTIFICIAL - 2010
 *
 * INTEGRANTES
    * CUCHETTI CARLOS              Leg. 47773
    * FLORES TREJO HUGO            Leg. 46367
    * GONZÁLEZ MÁRQUEZ VERÓNICA    Leg. 48076
    * ORTIZ,  MARTIN NICOLAS       Leg. 44886
 */
public class jugadoralumnogrupo25k2 extends Jugador
{
    private int[] jugada;
    private static int movimientosRestantes;
    private static int movimientosHechos;
    private Vector<Memoria> jugadasHechas;
    private int Ficha;

    public jugadoralumnogrupo25k2 (int cantFichas)
    {
      super(cantFichas);
      jugada= new int[4];
         jugada[0]=0;
         jugada[1]=0;
         jugada[2]=0;
         jugada[3]=1;
      movimientosRestantes=64;
      movimientosHechos=0;
      jugadasHechas= new Vector<Memoria>();

    }
    //Este es el metodo de jugar que se herada
    public int[] jugar(int tablero[][])
    {

        int aux;


            if (movimientosHechos < super.cantFichas)
            {

                jugada[0]=0;
                jugada[1]=0;

               if (movimientosHechos==0)
               {
                    /*LOGICA DE JUEGO: es generar al azar una jugada y verificar si no hay
                     fichas de cualquiera de los jugadores y ponerla si esta permitido
                   */

                    for( int k =0 ; k < 8; k++)
                    {
                        for (int l=0; l <8 ; l++)
                        {
                           if(tablero[k][l]!=0 && tablero[k][l] != super.numeroJugador )
                           {
                                //Aproximar ficha
                                aux= aleatorio(0, 1);
                                jugada[2]=k + aux;
                                if(aux==0){ jugada[3]= l + 1;}
                                      else{ jugada[3]=l;}
                           }
                        }
                     }


                    if (jugadaValida(tablero, jugada,0)!= true)
                    {
                        for (int a=movimientosRestantes; a >=0 ; a--)
                        {
                                aux= aleatorio(0, 7);
                                jugada[2]= aux;
                                aux= aleatorio(0, 7);
                                jugada[3]= aux;

                            if (jugadaValida(tablero, jugada,0) )
                            {
                                break;
                            }
                        }
                   }


               }
               else
               {  /*LOGICA DE JUEGO: es colocar una nueva ficha del juegador
                   y probarla en cada casillero posible el nodo se encarga de ver
                  si la jugada es valida segun si hay o no ficha en el casillero destino
                 */
                    if (super.numeroJugador==1)
                       { Ficha = 2; }
                    else
                       { Ficha = 1; }

                Arbol hacer= new Arbol(Ficha);
                hacer.Defender=true;

                for(int juego=0; juego < super.cantFichas; juego ++)
                {
                   //Generar Jugada
                   for (int fila=0; fila < 8; fila++ )
                   {
                       for (int columna=0; columna < 8; columna++)
                       {
                           jugada[2]= fila;
                           jugada[3]= columna;
                           if (jugadaValida(tablero, jugada,0))
                           {
                                hacer.add_Nodo(tablero,jugada,false);
                           }
                       } // for de columna
                   } // for de fila
                }// for de fichas

              jugada= hacer.get_MejorJugada();
             }

            Memoria nueva_jugada= new Memoria();
            nueva_jugada.fila= jugada[2];
            nueva_jugada.columna=jugada[3];
            movimientosHechos++;
            movimientosRestantes--;
            jugadasHechas.add(nueva_jugada);

            }
            else
            {
               /*LOGICA DE JUEGO: es Tomar cada una de las fichas del juegador
                 y probarla en cada casillero posible el nodo se encarga de ver
                si la jugada es valida segun si hay o no ficha en el casillero destino
               */
                Ficha= super.numeroJugador;

                Arbol hacer= new Arbol(Ficha);
                hacer.Defender=false;
                for(int juego=0; juego < super.cantFichas; juego ++)
                {
                   jugada[0]= jugadasHechas.elementAt(juego).fila;
                   jugada[1]=jugadasHechas.elementAt(juego).columna;
                   //Generar Jugada
                   for (int fila=0; fila < 8; fila++ )
                   {
                       for (int columna=0; columna < 8; columna++)
                       {
                           jugada[2]= fila;
                           jugada[3]= columna;
                           if(jugada[0]!=jugada[2] || jugada[1]!=jugada[3])
                           {
                                hacer.add_Nodo(tablero,jugada,true);
                           }
                       } // for de columna
                   } // for de fila
                }// for de fichas

            jugada= hacer.get_MejorJugada();
            guardarJugada(jugada[0],jugada[1],jugada[2],jugada[3]);
            movimientosHechos++;
            movimientosRestantes--;

           }

       // imprimirNuevaJugada();

        return jugada;
    }

   private int aleatorio(int min,int max)
   {
       return (int)(Math.random()*(max-min))+min;
   }

    public boolean jugadaValida (int[][] tablero,int[] jugada, int calleroVacio)
      {
           boolean r= false;
           int f;
           int c;

           f=jugada[2];
           c= jugada[3];

           if ( c < 0) { c=0; } // para evitar que se desborde no deberia pasar nunca.
           if ( f < 0) { f=0; } // para evitar que se desborde no deberia pasar nunca.
           if ( c > 7) { c=7; } // para evitar que se desborde no deberia pasar nunca
           if ( f > 7) { f=7; } // para evitar que se desborde no deberia pasar nunca

           //Verificar que la este vacio el casillero
           if(tablero[f][c]==calleroVacio) { r=true; }
                           else { r= false; }

           return r;
      }


   public void guardarJugada(int filaOrigen, int columnaOrigen, int filaDestino, int columnaDestino)
   {
       for( int i=0; i < super.cantFichas ; i++)
       {
           if (filaOrigen==jugadasHechas.elementAt(i).fila && columnaOrigen==jugadasHechas.elementAt(i).columna)
           {
               jugadasHechas.elementAt(i).fila= filaDestino;
               jugadasHechas.elementAt(i).columna= columnaDestino;
           }
       }
    }

    private void imprimirNuevaJugada()
    {

            String aux1 = null;
            int i;
            i = jugada[0];
            aux1= "{" + String.valueOf(i);
            i = jugada[1];
            aux1+= "," + String.valueOf(i);
            i = jugada[2];
            aux1+= "," + String.valueOf(i);
            i = jugada[3];
            aux1+= "," + String.valueOf(i) + "}";
            System.out.println ("Seleccionada: " + aux1 );


    }

   }


  class Memoria
  {
      public int fila;
      public int columna;

      public Memoria()
      {
          fila=0;
          columna=0;
      }
  }

  class Arbol
  {
         public Node raiz;  // Start node
         private int  auxPuntuacion;
         private int[] jugadaSeleccionada;
         int FichaJugador=0;
         boolean jugadaEncontrada= false;
         public boolean Defender;

         public Arbol()
         {
            raiz= new Node();
         }

         public Arbol (int set_fichaJugador)
         {
             raiz= new Node();
             FichaJugador= set_fichaJugador;
         }

         public Arbol (Node nuevaRaiz,int set_fichaJugador)
         {
             raiz = nuevaRaiz;
             this.FichaJugador=set_fichaJugador;
         }

         public void  add_Nodo (Node n)
         {
             raiz.add(n);
         }

         public void  add_Nodo (int[][] tablero,int[] jugada, boolean esMover)
         {
             raiz.add(tablero,jugada, FichaJugador, esMover);
         }

         public Node get_Nodo(int i)
         {
             return raiz.getNodo(i).getThis();
         }

         public Node get_Raiz()
         {
             return raiz;
         }

         public int[] get_MejorJugada()
         {
             auxPuntuacion=0;
             recorrerArbol(raiz);
             if (jugadaEncontrada== false)
             {
                 jugadaSeleccionada[0]=0;
                 jugadaSeleccionada[0]=0;
                 jugadaSeleccionada[0]=0;
                 jugadaSeleccionada[0]=1;

             }
             return jugadaSeleccionada;
         }

        private void recorrerArbol (Node n)
        {
            for( int j =0 ; j < n.cantidadHijos(); j++)
            {
                recorrerNodo(n.getNodo(j).getThis());
            }

        }


        private void recorrerNodo (Node n)
        {
          // System.out.println (n.toString());
            if (auxPuntuacion <= n.Puntuacion)
            {
                if(jugadaEncontrada==false)
                {
                   jugadaEncontrada=true;
                   auxPuntuacion=n.Puntuacion;
                   jugadaSeleccionada= n.getJugada();
                }
                else
                {
                    //Evaluar nuevas Alternativas: Solo en Ataque
                    if(Defender==false)
                    {
                        int opcion=0;
                        opcion= aleatorio(1, 3);
                        if (opcion == 1)
                        {
                            auxPuntuacion=n.Puntuacion;
                            jugadaEncontrada=true;
                            jugadaSeleccionada= n.getJugada();
                        }
                    }
                }
            }

            for(Node h: n.Hijos )
            {
                recorrerNodo(h);
            }

        }

       private int aleatorio(int min,int max)
       {
           return (int)(Math.random()*(max-min))+min;
       }

  } // fin del class Arbol


class Node
{
      public Vector<Node> Hijos;
      public Node ancesor;   // Nodo Padre
      public int Puntuacion;
      public int[] mejorJugada; // Local
      private int tamFilasTablero=8;
      private int tamColTablero=8;


      // Constructor
      public Node()
      {
            Hijos= new Vector<Node>();
            mejorJugada= new int[4];
            Puntuacion=0;

      }

         public Node(int[][] tablero,int[] jugada,int fichaJugador, boolean esMover)
        {

            Hijos= new Vector<Node>();
            mejorJugada= new int[4];
            mejorJugada[0]= jugada[0];
            mejorJugada[1]= jugada[1];
            mejorJugada[2]= jugada[2];
            mejorJugada[3]= jugada[3];
            puntuarJugada(tablero,mejorJugada,fichaJugador, esMover);

        }

      //  Verifica que los dos nodos sean iguales
       public boolean equals(Node n)
       {
            if (n.equals(this))
            {
              return true;
            } else
            {
              return false;
            }

      }

      private void puntuarJugada(int[][] tablero,int[] jugada,int fichaJugador,boolean esMover)
      {  int CantidadFichasLinea=0;
         int vaciosEntreFichas=0;
         int casilleroVacio=0; //Valor del casillero que se marca como vacio
         int c;
         int f;
         int pendiente;
         int fi;
         int ci;
         int aux1;
         int aux2;


          if (jugadaValida(tablero, jugada, fichaJugador,casilleroVacio,esMover))
          {
             f = jugada[2];
             c = jugada[3];

             if ( c < 0) { c=0; } // para evitar que se desborde no deberia pasar nunca.
             if ( f < 0) { f=0; } // para evitar que se desborde no deberia pasar nunca.
             if ( c > 7) { c=tamColTablero-1; } // para evitar que se desborde no deberia pasar nunca
             if ( f > 7) { f=tamFilasTablero-1; } // para evitar que se desborde no deberia pasar nunca

            /* ================================================
                       Verificar Validad Horizontal
            ================================================= */

              for ( int i=0; i < tamColTablero; i++)
              {
                  if(i==c) // Si es la nuevaJugada, simular Ficha
                  {
                      CantidadFichasLinea++;
                  }
                  else // Ver en el casillero del Tablero
                  {
                          if (tablero[f][i]==fichaJugador)
                          {
                            CantidadFichasLinea++;
                          }
                          else
                          {
                             if (tablero[f][i] == casilleroVacio) { vaciosEntreFichas++; }
                              if(vaciosEntreFichas > 1)
                              {
                                  CantidadFichasLinea=0;
                                  vaciosEntreFichas=0;
                              }
                          } //Fin de casilleros vacios
                   }

                   if (CantidadFichasLinea >= 3 || vaciosEntreFichas <= 1 )
                   {
                       CantidadFichasLinea+=90;
                       break;
                   }
              }

              Puntuacion += CantidadFichasLinea;
              vaciosEntreFichas=0;
            //Verificar Vertical

              for ( int i=0; i < tamFilasTablero; i++)
              {
                  if(i==f) // Si es la nuevaJugada, simular Ficha
                  {
                      CantidadFichasLinea++;
                  }
                  else // Ver en el casillero del Tablero
                  {
                          if (tablero[i][c]==fichaJugador)
                          {
                            CantidadFichasLinea++;
                          }
                          else
                          {
                             if (tablero[i][c] == casilleroVacio) { vaciosEntreFichas++; }
                              if(vaciosEntreFichas > 1)
                              {
                                  CantidadFichasLinea=0;
                                  vaciosEntreFichas=0;
                              }
                          } //Fin de casilleros vacios
                   }

                   if (CantidadFichasLinea >= 3)
                   {
                       CantidadFichasLinea+=90;
                       break;
                   }
               }
               Puntuacion+= CantidadFichasLinea;
               vaciosEntreFichas=0;
            //Verificar Diagonal 1

                pendiente = c - f;
                if (pendiente > 0)
                {  fi = 0;
                   ci = pendiente;
                }
                else
                {  ci = 0;
                   pendiente = Math.abs(pendiente);
                   fi = pendiente;

                 }

                  for (int i = fi; i < tamFilasTablero ; i++ )
                  {
                       if (Math.abs(i - ci) != pendiente) { break; }

                       if(i==f && ci ==c) // Si es la nuevaJugada, simular Ficha
                        {
                          CantidadFichasLinea++;
                        }
                       else // Ver en el casillero del Tablero
                       {
                          if (tablero[i][ci]==fichaJugador)
                          {
                            CantidadFichasLinea++;
                          }
                          else
                          {
                             if (tablero[i][ci] == casilleroVacio) { vaciosEntreFichas++; }
                              if(vaciosEntreFichas > 1)
                              {
                                  CantidadFichasLinea=0;
                                  vaciosEntreFichas=0;
                              }
                          } //Fin de casilleros vacios
                        }

                       if (CantidadFichasLinea >= 3)
                       {
                           CantidadFichasLinea+=90;
                           break;
                       }

                       ci++;
                       if (ci >= (tamFilasTablero-1)) { ci = tamFilasTablero-1; }
                   }
             Puntuacion+= CantidadFichasLinea;
             vaciosEntreFichas=0;
            //Verificar Diagonal 2

                pendiente = c + f;

                if (pendiente > (tamFilasTablero-1))
                {
                   ci = c - ((tamFilasTablero-1) - f);
                   fi = (tamFilasTablero-1);
                }

                else
                {
                   ci = 0;
                   fi = pendiente;

                 }

                  for(int i = fi; i >= 0 ; i--)
                  {
                    if (ci >= (tamFilasTablero-1)) { break; }

                      if(i==f && ci ==c) // Si es la nuevaJugada, simular Ficha
                        { CantidadFichasLinea++; }
                       else // Ver en el casillero del Tablero
                       {
                          if (tablero[i][ci]==fichaJugador)
                          {
                            CantidadFichasLinea++;
                          }
                          else
                          {
                             if (tablero[i][ci] == casilleroVacio) { vaciosEntreFichas++; }
                              if(vaciosEntreFichas > 1)
                              {
                                  CantidadFichasLinea=0;
                                  vaciosEntreFichas=0;
                              }
                          } //Fin de casilleros vacios
                        }

                       if (CantidadFichasLinea >= 3)
                       {
                           CantidadFichasLinea+=90;
                           break;
                       }

                    ci++;

                 }
                Puntuacion+= CantidadFichasLinea;

          }
          else  // La jugada no es valida
          {
              Puntuacion=0;
          }
       if (Puntuacion < 0) //Normalizar Puntuacion
       {
           Puntuacion=1;

       }

      }

      public boolean jugadaValida (int[][] tablero,int[] jugada, int fichaJugador,int  casilleroVacio, boolean esMover)
      {
           boolean r= false;
           int f;
           int c;
           int f2;
           int c2;


           f=jugada[0];
           c= jugada[1];
           f2=jugada[2];
           c2= jugada[3];

           if ( c < 0) { c=0; } // para evitar que se desborde no deberia pasar nunca.
           if ( f < 0) { f=0; } // para evitar que se desborde no deberia pasar nunca.
           if ( c > 7) { c=tamColTablero-1; } // para evitar que se desborde no deberia pasar nunca
           if ( f > 7) { f=tamFilasTablero-1; } // para evitar que se desborde no deberia pasar nunca
           if ( c2 < 0) { c2=0; } // para evitar que se desborde no deberia pasar nunca.
           if ( f2 < 0) { f2=0; } // para evitar que se desborde no deberia pasar nunca.
           if ( c2 > 7) { c2=tamColTablero-1; } // para evitar que se desborde no deberia pasar nunca
           if ( f2 > 7) { f2=tamFilasTablero-1; } // para evitar que se desborde no deberia pas


           //Verficar que la ficha sea mia o no haya fila
           if(esMover)
           {

           if (tablero[f][c]==fichaJugador && tablero[f2][c2]==casilleroVacio )
                                             { r= true; }
                                        else { r= false; }
           }
          else
          {
                if ( tablero[f2][c2]==casilleroVacio )
                                             { r= true; }
                                        else { r= false; }

          }


           return r;
      }

      public int getPuntuacion ()
      {
         return Puntuacion;
      }

      // Convert node to string
      public String toString()
      {
            String aux = null;
            int i;
            i = mejorJugada[0];
            aux= "{" + String.valueOf(i);
            i = mejorJugada[1];
            aux+= "," + String.valueOf(i);
            i = mejorJugada[2];
            aux+= "," + String.valueOf(i);
            i = mejorJugada[3];
            aux+= "," + String.valueOf(i);
            aux+= "} ;Puntuacion: " + String.valueOf(Puntuacion);
            return aux;
      }

      // Check for ancestors
      public boolean tieneAntecesor()
      {
            if (ancesor != null)
            {
              return true;
            }
            else
            {
              return false;
            }
      }


      public void add (Node nuevoHijo)
      {
          Hijos.add(nuevoHijo);
      }

      public void add (int[][] tablero,int[] jugada,int fichaJugador, boolean esMover)
      {
          Node nuevoHijo= new Node(tablero,jugada,fichaJugador,esMover);
          Hijos.add (nuevoHijo);
      }


      public  Node getNodo(int i)
      {
           return  Hijos.elementAt(i).getThis();
      }

      public int cantidadHijos()
      {
          return Hijos.size();
      }

      public int[] getJugada()
      {
          return mejorJugada;
      }
      public Node getThis()
      {
          return this;
      }

} // End class Node



